﻿using System;
using System.Web;
using HiTeachers.Utilities;

namespace HiTeachers.Data.Manager
{
    public class NHibernateSessionModule : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(BeginTransaction);
            context.EndRequest += new EventHandler(CommitAndCloseSession);
            context.Error += new EventHandler(Error);
        }

        /// <summary>
        /// Opens a session within a transaction at the beginning of the HTTP request.
        /// This doesn't actually open a connection to the database until needed.
        /// </summary>
        private static void BeginTransaction(object sender, EventArgs e)
        {
            // Do we need to open the transaction on the begin request?
            string url = HttpContext.Current.Request.Url.AbsolutePath;
            if (url.EndsWith(".aspx") || url.EndsWith(".ashx"))
            {
                NHibernateSessionManager.Instance.BeginTransaction();
            }
        }

        /// <summary>
        /// Commits and closes the NHibernate session provided by the supplied <see cref="NHibernateSessionManager"/>.
        /// Assumes a transaction was begun at the beginning of the request; but a transaction or session does
        /// not *have* to be opened for this to operate successfully.
        /// </summary>
        private static void CommitAndCloseSession(object sender, EventArgs e)
        {
            string url = HttpContext.Current.Request.Url.AbsolutePath;
            if (url.EndsWith(".aspx") || url.EndsWith(".ashx"))
            {
                try
                {
                    NHibernateSessionManager.Instance.CommitTransaction();
                }
                finally
                {
                    NHibernateSessionManager.Instance.CloseSession();
                }
            }
        }

        private static void Error(object sender, EventArgs e)
        {
            string url = HttpContext.Current.Request.Url.AbsolutePath;
            if (url.EndsWith(".aspx") || url.EndsWith(".ashx"))
            {
                Exception ex = HttpContext.Current.Error;
                Logger.Error(ex);

                NHibernateSessionManager sessionManager = NHibernateSessionManager.Instance;
                try
                {
                    sessionManager.RollbackTransaction();
                }
                finally
                {
                    sessionManager.CloseSession();
                }
            }
        }

        public void Dispose() { }
    }
}
